package cate.game.role.bag.heropart;

import cate.common.table.d.GDBag;
import cate.common.table.d.GDPart;
import cate.common.table.d.GDObj;
import cate.common.table.item.HeroPartCompositeRow;
import cate.common.table.item.HeroPartFreeCompositeRow;
import cate.common.table.item.HeroPartRow;
import cate.game.client.msg.MergeMsgSender;
import cate.game.event.hero.HeroCallOrCompositeEvent;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.bag.BagContainer;
import cate.game.role.bag.heropart.msg.HeroPartAddResp;
import cate.game.role.bag.item.msg.ItemAddResp;
import cate.game.role.bag.vo.TidNumVO;
import easy.java.practice.errorcode.EcResult;
import easy.java.util.StrTool;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Objects;

/**
 * 英雄碎片背包
 */
public class HeroPartBag extends BagContainer<HeroPart> {
    public HeroPartBag() {
    }

    public HeroPartBag(Role role) {
        super(role);
    }

    @Override
    protected byte getItemType() {
        return GDObj.Type.HERO_PART;
    }

    @Override
    public int calcCapacity() {
        return GDBag.Capcity.HERO_PART;
    }

    @Override
    protected ItemAddResp createItemAddMsg() {
        return new HeroPartAddResp();
    }

    @Override
    protected HeroPart createItem(int tid, long num) {
        return new HeroPart(role, tid, num);
    }

    @Override
    public HeroPartRow getItemTpl(int templateId) {
        return role.getGame().table.item.heroPart.get(templateId);
    }

    public void composite(int id, int num) {
        if (num <= 0) {
            role.getGame().notice.message(role, "请至少选择一个英雄");
            return;
        }
        if (role.getBag().hero.gridEmpty() < num) {
            role.getGame().notice.message(role, StrTool.format("英雄背包空间不足，请再腾出{}个格子再来合成吧", (num - role.getBag().hero.gridEmpty())));
            return;
        }
        HeroPartRow row = role.getGame().table.item.heroPart.get(id);
        if (row == null) {
            role.getGame().notice.message(role, "合成碎片选择有误");
            return;
        }

        if (row.type != GDPart.Type.NORMAL) {
            role.getGame().notice.message(role, "请求参数错误!");
            return;
        }

        // 合成消耗
        MixRes consume = new MixRes();
        consume.addItem(new MixResItem(GDObj.Type.HERO_PART, id, row.cost * num));
        EcResult<MixResItem> r = consume.consume(role, null);
        if (!r.ok()) {
            role.getGame().notice.message(role, r.message);
            return;
        }

        // 用于展示的奖励
        MixRes reward = new MixRes();
        if (row.rule == 0) {
            reward.addItem(new MixResItem(GDObj.Type.HERO, row.heroTid, num));
            publishEvent(role, new HeroCallOrCompositeEvent(role, row.heroTid, num));
        } else {
            for (int i = 0; i < num; i++) {
                HeroPartCompositeRow heroTpl = role.getGame().table.item.heroPartComposite.randomHero(row.rule);
                if (heroTpl != null) {
                    reward.addItem(new MixResItem(GDObj.Type.HERO, heroTpl.heroTid, 1));
                   publishEvent(role, new HeroCallOrCompositeEvent(role, heroTpl.heroTid, 1));
                }
            }
        }
        reward.add(role);
        role.getGame().notice.dialogReward(role, reward);
        role.getHistory().action.compositeHero();
    }

    public void chooseComposite(int id, int tid, int num) {
        if (num <= 0) {
            role.getGame().notice.message(role, "请至少选择一个英雄");
            return;
        }

        if (role.getBag().hero.gridEmpty() < num) {
            role.getGame().notice.message(role, StrTool.format("英雄背包空间不足，请再腾出{}个格子再来合成吧", num - role.getBag().hero.gridEmpty()));
            return;
        }
        HeroPartRow row = role.getGame().table.item.heroPart.get(id);
        if (row == null) {
            role.getGame().notice.message(role, "自选碎片配置错误");
            return;
        }

        if (row.type != GDPart.Type.CHOOSE) {
            role.getGame().notice.message(role, "请求参数错误!");
            return;
        }

        HeroPartCompositeRow hpRow = role.getGame().table.item.heroPartComposite.chooseHero(row.rule, tid);
        if (Objects.isNull(hpRow)) {
            role.getGame().notice.message(role, "选择英雄不存在或配置错误");
            return;
        }

        // 合成消耗
        MixRes consume = new MixRes();
        consume.addItem(new MixResItem(GDObj.Type.HERO_PART, id, row.cost * num));
        EcResult<MixResItem> r = consume.consume(role, null);
        if (!r.ok()) {
            role.getGame().notice.message(role, r.message);
            return;
        }

        MixRes rwd = new MixRes();
        rwd.addItem(new MixResItem(GDObj.Type.HERO, tid, num));
        rwd.add(role);
        role.getGame().notice.dialogReward(role, rwd);
        publishEvent(role, new HeroCallOrCompositeEvent(role, tid, num));
    }

    public void sell(List<TidNumVO> items) {
        if (CollectionUtils.isEmpty(items)) {
            role.getGame().notice.message(role, "出售碎片有误");
            return;
        }
        MergeMsgSender sender = new MergeMsgSender();
        MixRes reward = new MixRes();
        for (TidNumVO vo : items) {
            if (vo.num <= 0) {
                role.getGame().notice.message(role, "出售数量有误");
                continue;
            }
            if (count(vo.tid) < vo.num) {
                role.getGame().notice.message(role, "道具数量不足");
                continue;
            }
            HeroPartRow baseTpl = getItemTpl(vo.tid);
            MixRes sellRes = null;
            if (baseTpl != null && !StringUtils.isBlank(baseTpl.rewardConfig) && !StringUtils.equals("0", baseTpl.rewardConfig)) {
                sellRes = new MixRes(baseTpl.rewardConfig);
            }
            if (sellRes == null) {
                role.getGame().notice.message(role, "该碎片不支持出售");
                continue;
            }
            EcResult<Void> r = sellRes.multiply(vo.num).add(role, sender);
            if (!r.ok()) {
                role.getGame().notice.message(role, r, true);
                continue;
            }
            removeItem(vo.tid, vo.num, sender);
            reward.addList(sellRes);
        }
        sender.send(role, true);
        role.getGame().notice.dialogReward(role, reward);
    }

    /**
     * 二级自选合成碎片
     *
     * @param id  碎片id
     * @param tid 英雄id
     * @param num 数量
     */
    public void chooseFreeComposite(int id, int tid, int num, int rule) {
        if (num <= 0) {
            role.getGame().notice.message(role, "请至少选择一个英雄");
            return;
        }

        if (role.getBag().hero.gridEmpty() < num) {
            role.getGame().notice.message(role, StrTool.format("英雄背包空间不足，请再腾出{}个格子再来合成吧", num - role.getBag().hero.gridEmpty()));
            return;
        }

        HeroPartRow row = role.getGame().table.item.heroPart.get(id);
        if (row == null) {
            role.getGame().notice.message(role, "自选碎片配置错误");
            return;
        }

        if (row.type != GDPart.Type.TWICE_CHOOSE) {
            role.getGame().notice.message(role, "请求参数错误!");
            return;
        }

        HeroPartCompositeRow hpRow = role.getGame().table.item.heroPartComposite.chooseHero(rule, tid);
        if (Objects.isNull(hpRow)) {
            role.getGame().notice.message(role, "选择英雄不存在或配置错误");
            return;
        }

        HeroPartFreeCompositeRow freeHpRow = role.getGame().table.item.free.chooseRowByTidAndRule(id, rule);

        if (freeHpRow == null) {
            log.debug("万能碎片合成配置错误");
            return;
        }

        // 合成消耗
        MixRes consume = new MixRes();
        consume.addItem(new MixResItem(GDObj.Type.HERO_PART, id, num * freeHpRow.num));
        EcResult<MixResItem> r = consume.consume(role, null);
        if (!r.ok()) {
            role.getGame().notice.message(role, r.message);
            return;
        }

        MixRes rwd = new MixRes();
        rwd.addItem(new MixResItem(GDObj.Type.HERO, tid, num));
        rwd.add(role);
        role.getGame().notice.dialogReward(role, rwd);
        publishEvent(role, new HeroCallOrCompositeEvent(role, tid, num));
    }
}
